package xj.model.uml;

import static xj.model.uml.UMLModelConstants.ROLE_ACTOR;
import static xj.model.uml.UMLModelConstants.ROLE_SYSTEM;
import static xj.model.uml.UMLModelConstants.ROLE_USE_CASE;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import xj.meta.ModelElement;

public class UseCaseDiagram extends UMLDiagram {

  public UseCaseDiagram() {
    setType(DiagramType.Use_Case_Diagram);
  }

  public UseCaseDiagram(String name) {
    super(name);
    setType(DiagramType.Use_Case_Diagram);
  }
  @Override
  public boolean checkAllowedEdge(ModelElement m) {
    if (m != null &&
	m instanceof UMLAssociation) { 
      return true;
    }       
    return false; 
  }

  @Override
  public boolean checkAllowedNode(ModelElement m) { 
    if (m != null && 
	(m instanceof Actor ||
	 m instanceof UMLSystemBoundary ||
	 m instanceof UseCase ||
	 m instanceof Note)) {
      return true;
    }
    return false; 
  }

  @Override
  public boolean checkAllowSubnode(ModelElement parentModel, 
				   ModelElement nodeModel) {
    if (parentModel instanceof UMLSystemBoundary) { 
      return (nodeModel instanceof Actor ||
	      nodeModel instanceof UseCase);
    }
    return false; 
  }

  public void addUseCase(UseCase u) {
    if (u != null) {
      usecases.add(u);
      addOwnedElement(u, ROLE_USE_CASE);
    }
  }

  public void removeUseCase(UseCase u) {
    if (u != null) {
      usecases.remove(u);
      removeOwnedElement(u);
    }
  }

  public Set<UseCase> getUseCases() {
    return usecases;
  }

  public void addActor(Actor a) {
    if (a != null) {
      actors.add(a);
      addOwnedElement(a, ROLE_ACTOR);
    }
  }

  public void removeActor(Actor a) {
    if (a != null) {
      actors.remove(a);
      removeOwnedElement(a);
    }
  }

  public Set<Actor> getActors() {
    return actors;
  }

  public void addSystem(UMLSystemBoundary s) {
    if (s != null) {
      systems.add(s);
      addOwnedElement(s, ROLE_SYSTEM);
    }
  }

  public void removeSystem(UMLSystemBoundary s) {
    if (s != null) {
      systems.remove(s);
      removeOwnedElement(s);
    }
  }

  public Set<UMLSystemBoundary> getSystems() {
    return systems;
  }

  @Override
  public void deconstruct() {
    super.deconstruct();
    usecases.clear();
    actors.clear();
    systems.clear();
  }

  @Override
  public void add(ModelElement parent, ModelElement e, Object arg) {
    if (e != null) {
      if (e instanceof UseCase) {
	if (parent instanceof UMLSystemBoundary) {
	  ((UMLSystemBoundary) parent).addUseCase((UseCase) e);
	} else {
	  addUseCase((UseCase) e);
	}
      } else if (e instanceof Actor) {
	addActor((Actor) e);
      } else if (e instanceof UMLSystemBoundary) {
	addSystem((UMLSystemBoundary) e);
      } else {
	super.add(parent, e, arg);
      }
    }
  }

  @Override
  public String toString() {
    return "ClassDiagrm: name=" + name;
  }

  @Override
  public Object clone() throws CloneNotSupportedException {
    UseCaseDiagram d = (UseCaseDiagram) super.clone();

    d.usecases = new HashSet<UseCase>();
    Iterator<UseCase> iter1 = usecases.iterator();
    while (iter1.hasNext()) {
      UseCase u = iter1.next();
      d.addUseCase((UseCase) u.clone());
    }

    d.actors = new HashSet<Actor>();
    Iterator<Actor> iter2 = actors.iterator();
    while (iter2.hasNext()) {
      Actor a = iter2.next();
      d.addActor((Actor) a.clone());
    }

    d.systems = new HashSet<UMLSystemBoundary>();
    Iterator<UMLSystemBoundary> iter4 = systems.iterator();
    while (iter4.hasNext()) {
      UMLSystemBoundary s = iter4.next();
      d.addSystem((UMLSystemBoundary) s.clone());
    }

    return d;
  }

  protected Set<UseCase> usecases = new HashSet<UseCase>();

  protected Set<Actor> actors = new HashSet<Actor>();

  protected Set<UMLSystemBoundary> systems = new HashSet<UMLSystemBoundary>();

}
